<?php
/**
 * 登录
 * @return
 * @author yuncran@126.com
 */

namespace app\api\controller;

use app\BaseController;
use app\model\ConfigModel;
use app\model\DrawLogModel;
use app\model\FriendModel;
use app\model\UserInviteModel;
use app\model\UserModel;
use app\services\UserService;
use GatewayClient\Gateway;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use thans\jwt\facade\JWTAuth;
use think\App;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Session;


class Login extends BaseController
{

    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 构造方法
     * @access public
     * @param App $app 应用对象
     */
    public function __construct(App $app)
    {
        Gateway::$registerAddress = config('gateway.registerAddress');
        $this->app = $app;
        $this->request = $this->app->request;

        // 控制器初始化
        // $this->initialize();
    }


    public function login()
    {
        //查询ip 是否
//        $verify = UserService::getIp($this->request->ip());
//        if (!$verify) {
//            $config = ConfigModel::getSensitive(['id' => 17]);
//            return $this->renderError(lang('您是国内ip不能登录、请联系平台: ' . $config['value']));
//        }
        $param = request()->param();
        $token = $param['token'] ?? '';
        // token一键登录
        if ($token) {
            $apiStatus = config('app.api_status');
            if (!$apiStatus) {
                return $this->renderError(lang('接口已关闭'));
            }
            $userInfo = Cache::get($token);
            if (!$userInfo) {
                return $this->renderError(lang('TOKEN已失效！'));
            }
        } else {
            $userInfo = UserModel::where(['account' => $param['account']])->whereOr(['email' => $param['account']])
                ->whereOr(['nickname' => $param['account']])
                ->withoutField('joinip,login_count,update_time,create_time')->find();
            if ($userInfo == null) {
                return $this->renderError(lang('当前用户不存在！'));
            }
            if ($userInfo['is_examine'] == 1) {
                return $this->renderError(lang('请等待审核通过后操作'));
            }
            $userInfo['user_id'] = $userInfo['id'];
            if ($userInfo['status'] == 'hidden') {
                return $this->renderError(lang('您的账号已被禁用'));
            }
            $password = password_hash_tp($param['password'], $userInfo['salt']);
            $code = $param['code'] ?? '';
            if ($code) {
                if ($code != Cache::get($param['account'])) {
                    return $this->renderError(lang('验证码错误'));
                }
                Cache::delete($param['account']);
            } else {
                if ($password != $userInfo['password']) {
                    return $this->renderError(lang('密码错误!'));
                }
            }
        }
        $userInfo['avatar'] = avatarUrl($userInfo['avatar'], $userInfo['realname'], $userInfo['user_id']);

        //如果登录信息中含有client——id则自动进行绑定
        $client_id = $this->request->param('client_id');
        if ($client_id) {
            $this->doBindUid($userInfo['user_id'], $client_id);
        }
        $update = [
            'logintime' => time(),
            'loginip' => $this->request->ip(),
            'login_count' => Db::raw('login_count+1'),
            'verification' => $userInfo['online_status'] == 1 ? 'normal' : $userInfo['verification'], // 上线=normal , 下线=hidden
        ];
        UserModel::where('id', $userInfo['user_id'])->save($update);
        $userInfo['qrUrl'] = request()->domain() . '/scan/u/' . encryptIds($userInfo['user_id']);
        unset($userInfo['password'], $userInfo['salt']);
        $userInfo['displayName'] = $userInfo['realname'];
        $userInfoToken = ['user_id' => $userInfo['id'], 'merchant_id' => $userInfo['merchant_id'], 'status' => $userInfo['status'], 'gender' => $userInfo['gender']];

        $authToken = UserModel::refreshToken($userInfoToken,'web');
        $data = [
            'sessionId' => Session::getId(),
            'authToken' => $authToken,
            'userInfo' => $userInfo
        ];
        #登录通知 告知Ta
//        wsSendMsg(0, 'login', ['id' => $userInfo['user_id'], 'is_login' => 'normal']);
        return $this->renderSuccess($data, lang('登录成功！'));
    }


    /**
     * 注册用户 {"0":"关闭","1":"男女都需要审核","2":"只男生需要审核","3":"只女生需要审核"}
     * @return \think\response\Json
     * @author yuncran@126.com
     */
    public function register()
    {

        $verify = UserService::getIp($this->request->ip());
//        if (!$verify) return $this->renderError(lang('暂时不支持国内ip、请联系平台: '));

        $this->startTrans();
        try {
            $data = $this->request->param();
            $validate = new \think\Validate();
            $message = array(
                'account.require' => lang('邮箱必填'),
                'avatar.require' => lang('头像必填'),
                'account.email' => lang('邮箱格式不符'),
                'nickname.require' => lang('昵称必填'),
                'nickname.max' => lang('会员昵称不能超过30个字符'),
                'password.require' => lang('密码必填'),
                'password.min' => lang('密码长度不能小于6个字符'),
                'password.max' => lang('密码长度在6~15个字符'),
                'password_confirm.require' => lang('确认密码必填'),
            );
            $check = $validate->message($message)->check($data,
                [
                    'nickname' => 'require|max:30',
                    'account' => 'require|email',
                    'password' => 'require|min:6|max:15',
                    'password_confirm' => 'require',
                    'avatar' => 'require',
                ]
            );
            if (!$check) return $this->renderError($validate->getError());
            if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $data['nickname'])) {
                return $this->renderError(lang('不能有中文字符'));
            }            
            // 判断系统是否开启注册
            $apiStatus = config('app.api_status');
            if ($apiStatus != 1) return $this->renderError(lang('当前系统已关闭注册功能！'));
            if ($data['password'] != $data['password_confirm']) return $this->renderError(lang('两次密码输入的不一致！'));
            if (!isPasswordSimple($data['password'])) return $this->renderError(lang('您输入的密码太简单了！'));
            $user = new UserModel();

            $verify = $user->checkAccount($data);
            if (!$verify) {
                return $this->renderError($user->getError());
            }
            $userInfo = UserModel::where(['account' => $data['account']])
                ->whereOr(['email' => $data['account']])
                ->withoutField('joinip,login_count,update_time,create_time')->find();
            if ($userInfo) {
                return $this->renderError(lang('您的账号已重复'));
            }

            $userInfo = UserModel::where(['nickname' => $data['nickname']])
                ->withoutField('joinip,login_count,update_time,create_time')->find();
            if ($userInfo) {
                return $this->renderError(lang('您的账号已重复'));
            }

            $salt = \utils\Str::random(4);
            $data['password'] = password_hash_tp($data['password'], $salt);
            $data['salt'] = $salt;
            $data['joinip'] = $this->request->ip();
//            $data['nickname'] = pinyin_sentence($data['nickname']);
            $data['email'] = $data['account'];
            $data['status'] = 'normal';
            $data['verification'] = 'hidden';
            $int_time = time();
            $data['jointime'] = $int_time;
            $data['prevtime'] = $int_time;
            $data['createtime'] = $int_time;
            $data['updatetime'] = $int_time;
            $data['expire_time'] = date('Y-m-d H:i:s', $int_time);
            //查找邀请记录
            $userInvite = UserInviteModel::where(['email' => $data['email']])->find();
            if (empty($data['invite'])) {
                $user->pid = empty($userInvite->user_id) ? 0 : $userInvite->user_id;
                $merchant_id = 0;
            } else {
                $user->pid = empty($data['invite']) ? 0 : $data['invite'];
                $merchant = (new UserModel())->where('id', $user->pid)->value('merchant_id');
                $merchant_id = isset($data['merchant_id']) ? $data['merchant_id'] : $merchant;
            }
            $set_user_status = ConfigModel::where('name', 'set_user_status')->value('value');
            $is_examine = 0;
            if ($set_user_status > 0) {
                if ($set_user_status == 1) {
                    $is_examine = 1;
                } elseif ($set_user_status == 2) {
                    if ($data['gender'] == 1) {
                        $is_examine = 1;
                    }
                } elseif ($set_user_status == 3) {
                    if ($data['gender'] == 0) {
                        $is_examine = 1;
                    }
                }
            }
            $data['is_examine'] = $is_examine;
            $data['merchant_id'] = isset($data['merchant_id']) ? $data['merchant_id'] : $merchant_id;
            $user->save($data);
            if ($userInvite) {
                UserInviteModel::where(['email' => $data['email']])->update(['to_user_id' => $user->getLastInsID(), 'status' => 1]);
                UserModel::addUserInc($user->pid, 'score', 50);
            }
            if (!empty($data['invite'])) {
                UserInviteModel::create([
                    'user_id' => $data['invite'],
                    'to_user_id' => $user->getLastInsID(),
                    'type' => 2,
                    'url' => $this->request->host() . '/web/dist/#/signin?invite=' . $data['invite'],
                    'status' => 1,
                    'create_time' => date('Y-m-d H:i:s', time())
                ]);
                UserModel::addUserInc($user->pid, 'score', 50);
            }
            $data['user_id'] = $user['id'];
            $userInfoToken = ['user_id' => $user['id'], 'merchant_id' => $data['merchant_id'], 'status' => $user['status'], 'gender' => $user['gender']];
            $data['sessionId'] = Session::getId();
            $data['authToken'] = UserModel::refreshToken($userInfoToken,'web');
            /** 增加客服好友 */
            $basic_service = ConfigModel::where('name', 'basic_service')->value('value');
            if ($basic_service > 0) {
                $userInfo1 = UserModel::where(['id' =>$basic_service])->withoutField('joinip,login_count,update_time,create_time')->find();
                if($userInfo1){
                    $arr = [$user['id'], $basic_service];
                    sort($arr);
                    $relation = implode(',', $arr) . ',';
                    FriendModel::create([
                        'create_user' => $user['id'],
                        'friend_user_id' => $basic_service,
                        'create_time' => time(),
                        'update_time' => time(),
                        'relation' => $relation,
                    ]);
                }
            }
            unset($data['password'], $data['salt']);
            // 监听用户注册后的操作  event('UserRegister', $data);
            event('Register', $data);
            $this->commit();
            return $this->renderSuccess($data, lang('注册成功！'));
        } catch (\Exception $e) {
            $this->rollback();
            return $this->renderError($e->getMessage());
        }

    }

    /**
     * 语言类型
     * @return \think\response\Json
     * @author yuncran@126.com
     */
    public function getLanguage()
    {
        return $this->renderSuccess(config('langue'), lang('查询成功'));
    }

    /**
     * 退出登录
     * @return \think\response\Json
     * @author yuncran@126.com
     */
    public function logout()
    {
        try {
            $jwtData = JWTAuth::auth();
        } catch (\Exception $e) {
            return $this->renderError(lang('退出成功！'));
        }

        $userInfo = $jwtData['info']->getValue();
        //解密token中的用户信息
        $userInfo = str_encipher($userInfo, false, config('app.aes_token_key'));

        if (!$userInfo) {
            return $this->renderError(lang('退出成功！'));
        }
        //解析json
        $userInfo = (array)json_decode($userInfo, true);

        if ($userInfo) {
            $client_id = $this->request->param('client_id', '');
            if ($client_id) {
                Gateway::unbindUid($client_id, $userInfo['user_id']);
            }
            wsSendMsg(0, 'isOnline', ['id' => $userInfo['user_id'], 'is_online' => 'hidden']);
        }
        // 上线=normal , 下线=hidden
        $update = ['verification' => 'hidden', 'updatetime' => time()];
        UserModel::where('id', $userInfo['user_id'])->update($update);

        JWTAuth::invalidate(JWTAuth::token()->get());
        return $this->renderSuccess([], lang('退出成功！'));
    }

    //头像生成
    public function avatar()
    {
        return circleAvatar(input('str'), input('s') ?: 80, input('uid'));
    }

    /**
     * 将用户UId绑定到消息推送服务中
     * @return \think\response\Json
     */
    public function bindUid()
    {
        $client_id = $this->request->param('client_id');
        $user_id = $this->request->param('user_id');
        $cid = $this->request->param('cid', '');
        try {
            $this->doBindUid($user_id, $client_id, $cid);
        } catch (\Exception $e) {
            // 未找到用户
        }
        return $this->renderSuccess('ok');
    }

    // 执行绑定
    public function doBindUid($user_id, $client_id)
    {
        // 如果当前ID在线，将其他地方登陆挤兑下线
        if (Gateway::isUidOnline($user_id)) {
            wsSendMsg($user_id, 'offline', ['id' => $user_id, 'client_id' => $client_id, 'isMobile' => $this->request->isMobile()]);
        }
        Gateway::bindUid($client_id, $user_id);
        wsSendMsg(0, 'isOnline', ['id' => $user_id, 'is_online' => 1]);
    }

    // 下线通知
    public function offline()
    {
        $user_id = input('user_id');
        try {
            $client_ids = Gateway::getClientIdByUid($user_id);
            // 一个终端登录时才发送下线通知
            if (count($client_ids) < 2) {
                wsSendMsg(0, 'isOnline', ['id' => $user_id, 'is_online' => 0]);
            }
        } catch (\Exception $e) {
            // 未找到用户
        }
        return success('');
    }

    /**
     * 将用户团队绑定到消息推送服务中
     * @return \think\response\Json
     */
    public function bindGroup()
    {
        $client_id = input('client_id');
        $group_id = input('group_id');
        $group_id = explode('-', $group_id)[1];
        Gateway::joinGroup($client_id, $group_id);
        return success('');
    }


    /**获取系统配置信息
     * @return \think\response\Json
     * @author yuncran@126.com
     */
    public function getSystemInfo()
    {
        $systemInfo = ConfigModel::getSystemInfo();
        $systemInfo['demon_mode'] = env('app.demon_mode', false);
        return success(lang('查询成功'), $systemInfo);
    }

    public function android()
    {
        return rtrim(request()->domain(), '/android') . 'android.spk';
    }

    // 检查app版本升级
    public function checkVersion()
    {
        $oldRelease = $this->request->param('release', 0);
        $setupPage = $this->request->param('setupPage', false);
        $platform = $this->request->param('platform', 1101);
        $config = Config::where('name', 'sysInfo')->value('value');
        if ($platform == 1101) {
            $teminal = 'andriod';
        } else {
            $teminal = 'ios';
        }
        $versionInfo = config('version.' . $teminal);
        $data = [
            'versionName' => $versionInfo['version'],
            'versionCode' => $versionInfo['release'],
            'updateType' => $versionInfo['update_type'],
            'versionInfo' => $versionInfo['update_info'],
            'downloadUrl' => '',
        ];
        // 是否手动检测更新，是的话就不能强制更新或者静默更新
        if ($setupPage) {
            $data['updateType'] = 'solicit';
        }
        // 如果旧版本大于等于当前版本则不更新
        if ($oldRelease >= $versionInfo['release']) {
            return success('', $data);
        }
        $downUrl = '';
        $andriod = getAppDowmUrl('andriod');
        // 如果是ios则返回ios地址
        if ($platform == 1101) {
            $downUrl = env('app.andriod_webclip', '') ?: $andriod;
        } else {
            $downUrl = env('app.ios_webclip', '');
        }
        $data['downloadUrl'] = $downUrl;
        return success('', $data);
    }


    /**
     * 发送邮箱
     * @author yuncran@126.com
     */
    public function sendSms()
    {
        $param = $this->request->param();
        $validate = new \think\Validate();
        $message = array(
            'email.require' => lang('邮箱必填'),
            'email.email' => lang('邮箱格式不符'),
        );
        $check = $validate->message($message)->check($param,
            [
                'email' => 'require|email',
            ]
        );
        if (!$check) return $this->renderError($validate->getError());
        $mail = new PHPMailer(true);
        try {
            $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      //Enable verbose debug output
            $mail->isSMTP();                                            //Send using SMTP
            $mail->Host = 'smtp.163.com';                               //Set the SMTP server to send through
            $mail->SMTPAuth = true;                                     //Enable SMTP authentication
            $mail->Username = 'yuncran@163.com';                             //SMTP username
            $mail->Password = 'YXGZYDUEOBBPANRN';                                 //SMTP password
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;             // 启用 TLS 加密
//            $mail->Port = 25;                                              // TCP 端口
            $mail->Port = 25;                                              // TCP 端口
            //Recipients
            $mail->setFrom('yuncran@163.com', 'yuncran');       // 发件人
            $mail->addAddress($param['email']);                             // 收件人
            //Content
            $mail->isHTML(true);
            $code = rand(100000, 999999);
            //进行缓存code 五分钟
            $key = 'email' . $param['email'];
            Cache::set($key, $code, 300);
            $mail->Subject = "ycr";
            $mail->Body = "Your verification code is: $code Please do not tell anyone";
//dd( mail());
            $mail->send();
        } catch (\Throwable $throwable) {
            var_export($throwable->getTraceAsString());
            return $this->renderError(lang('系统异常!设置的授权码时效了'));
        }
        return $this->renderSuccess([], lang('发送成功'));
    }


}